//
//  HistoryLog.m - a collection of History
//  iMed
//
//  Created by Barry Press on 10/28/09.
//  Copyright 2009 Barry Press. All rights reserved.
//

#import "HistoryLog.h"
#import "DataSet.h"

@implementation HistoryLog

#pragma mark Operations on the history records
// ---------------------------------------------- sortedHistoryForRX -----------
- (HistoryLog*)sortedHistoryForRX:(RX*)anRX
{
	HistoryLog* log = [[[HistoryLog alloc] init] autorelease];
	NSUInteger i, count = [histories count];
	for (i = 0; i < count; i++) {
		History* obj = [histories objectAtIndex:i];
		if ([obj rx] == anRX) {
			[log addObject:obj];
		}
	}
	return [log sortedByDate];
}

// ---------------------------------------------- sortedByDate -----------------
- (HistoryLog*)sortedByDate
{
//	NSArray* sortDesc = [[NSArray arrayWithObjects:[[NSSortDescriptor alloc] 
//												   initWithKey:@"timestamp" 
//												   ascending:YES], 
//												  nil] autorelease];
	NSArray* sortDesc = [NSArray arrayWithObjects:[[NSSortDescriptor alloc] 
													initWithKey:@"timestamp" 
													ascending:YES], 
						  nil];
	
	[histories sortUsingDescriptors:sortDesc];
	return self;
}
// ---------------------------------------------- priorRXHistory ---------------
- (History*)priorRXHistory:(RX*)anRX
{
	return [[[self sortedHistoryForRX:anRX] histories] lastObject];
}

// ---------------------------------------------- previousDayRXHistory ---------
- (History*)previousDayRXHistory:(RX*)anRX forHistory:(History*)aHistory 
					   inDataSet:(DataSet*)ds returnsCount:(int*)aCount 
				 andNewerHistory:(History**)newerHistory
{
	HistoryLog* log = [self sortedHistoryForRX:anRX];
	History* hist = nil;
	NSDate *theDate;
	
	if (aCount != NULL) {
		*aCount = 0;
	}
	if (newerHistory != NULL) {
		*newerHistory = nil;
	}
	
	// log is a subset of the history for this rx, sorted by time from oldest
	// at 0. Find the occurrence of the given history entry in the log if one
	// was specified, else assume we start at the end of the log
	NSUInteger i, count = [log count], hIndex;
	if (aHistory != nil) {
		for (i = count-1; i >= 0; i--) {
			History * obj = [log objectAtIndex:i];
			if (obj == aHistory) {
				if (newerHistory != NULL) {
					*newerHistory = aHistory;
				}
				break;
			}
		}
		theDate = [aHistory timestamp];
		hIndex = i;
	}
	else {
		hIndex = count-1;
		if (newerHistory != NULL) {
			*newerHistory = [log lastObject];
		}
		theDate = [[log lastObject] timestamp];
	}

	
	// If the given history is there, find the first history for the previous
	// day and return that, or else we'll return nil
	for (i = hIndex-1; i >= 0; i--) {
		History * obj = [log objectAtIndex:i];
		if (![ds isDate:theDate onSameDayAsDate:[obj timestamp]]) {
			hist = obj;
			if (aCount != NULL) {
				*aCount = hIndex - i;
			}
			break;
		}
	}
	return hist;
}

#pragma mark Collection methods
// ---------------------------------------------- addObject --------------------
- (void)addObject:(History*)aHistory
{
	[histories addObject:aHistory];
}

// ---------------------------------------------- count ------------------------
- (int)count
{
	NSAssert(histories != NULL, @"NULL array pointer in histories:count");
	return [histories count];
}

// ---------------------------------------------- lastObject -------------------
- (History*)lastObject
{
	return [histories lastObject];
}

// ---------------------------------------------- objectAtIndex ----------------
- (History*)objectAtIndex:(int)index
{
	NSAssert(histories != NULL, @"NULL array pointer in histories:objectAtIndex");
	return [histories objectAtIndex:index];
}

// ---------------------------------------------- removeAllObjects -------------
- (void)removeAllObjects
{
	NSAssert(histories != NULL, @"NULL array pointer in histories:removeAllObjects");
	[histories removeAllObjects];
}

// ---------------------------------------------- removeObject -----------------
- (void)removeObject:(NDCitem*)anObject
{
	NSAssert(histories != NULL, @"NULL array pointer in histories");
	[histories removeObject:anObject];
}

#pragma mark Archiving methods

// ---------------------------------------------- dealloc ----------------------
- (void)dealloc
{
	NSAssert(histories != NULL, @"NULL array pointer in histories:removeObject");
	[histories release];
	histories = NULL;
	[super dealloc];
}

// ---------------------------------------------- init -------------------------
- (id)init
{
	[super init];
	histories = [[[NSMutableArray alloc] init] retain];
	NSAssert(histories != NULL, @"NULL array pointer in histories:init");
	return self;
}

// ---------------------------------------------- encodeWithCoder --------------
- (void)encodeWithCoder:(NSCoder *)coder
{
	NSAssert(histories != NULL, @"NULL array pointer in histories:encodeWithCoder");
	[coder encodeObject:histories forKey:@"historiesArray"];
}

// ---------------------------------------------- initWithCoder ----------------
- (id)initWithCoder:(NSCoder *)coder
{
	[super init];
	histories = [[coder decodeObjectForKey:@"historiesArray"] retain];
	NSAssert(histories != NULL, @"NULL array pointer in histories:initWithCoder");
	return self;
}

@synthesize histories;
	 
@end
